﻿/***************************************************************
<OWNER> = Raul Huertas Paiva
<ORGANIZATION> = None
<YEAR> = 2013

In the original BSD license, both occurrences of the phrase "COPYRIGHT HOLDERS AND CONTRIBUTORS" in the disclaimer read "REGENTS AND CONTRIBUTORS".

Here is the license template:

Copyright (c) 2013, Raul Huertas Paiva
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

***************************************************************/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;
using NFCfyMe.Resources;
using System.Collections.ObjectModel;
using Windows.Networking.Proximity;
using Windows.Networking.Sockets;
using System.Runtime.InteropServices.WindowsRuntime;

namespace NFCfyMe
{
    public class BluetoothDeviceRecord
    {
        public string Name { get; set; }
        public PeerInformation PeerInfo { get; private set; }


        public BluetoothDeviceRecord(PeerInformation peer)
        {
            PeerInfo = peer;
            Name = this.PeerInfo.DisplayName;
        }

        public override string ToString()
        {
            return Name + ", " + PeerInfo.HostName + ", " + PeerInfo.ServiceName;
        }
    }

    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        private ObservableCollection<BluetoothDeviceRecord> myMusicList = new ObservableCollection<BluetoothDeviceRecord>();
        private bool transmitting = false;
        private int messageNumber = 0;

        private ProximityDevice _device;
        private long _subscriptionIdNdef;
        private long _publishingMessageId;


        public string nextMessageNumber() {
            int ret = messageNumber;
            messageNumber++;
            return ret+": ";
        }

        public MainPage()
        {
            InitializeComponent();
            myListPicker.DataContext = myMusicList;
        }

        private void myListPicker_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            if (myListPicker.SelectedItem == null)
            {
                //No hacer nada
            }
            else { 
            
            }
        }
        
        /**Funcion para ir a la configuración de bluetooth*/
        private void ShowBluetoothcControlPanel()
        {
            ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask();
            connectionSettingsTask.ConnectionSettingsType = ConnectionSettingsType.Bluetooth;
            connectionSettingsTask.Show();
        }

        private void findDevicesButton_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            RefreshPairedDevicesList();
        }

        private async void RefreshPairedDevicesList() {
            findDevicesProgressBar.IsIndeterminate = true;
            try
            {
               
                // Search for all paired devices
                PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
                
                var peers = await PeerFinder.FindAllPeersAsync();
                // By clearing the backing data, we are effectively clearing the ListBox
                myMusicList.Clear();

                if (peers.Count == 0)
                {
                    logLine1.Text = nextMessageNumber() + AppResources.devicesNotFound;
                }
                else
                {
                    // Found paired devices.
                    foreach (var peer in peers)
                    {
                        myMusicList.Add(new BluetoothDeviceRecord(peer));
                    }
                }
                
            }
            catch (Exception ex)
            {
                if ((uint)ex.HResult == 0x8007048F)
                {
                    var result = MessageBox.Show(AppResources.Msg_BluetoothOff, AppResources.bluetoothOff, MessageBoxButton.OKCancel);
                    if (result == MessageBoxResult.OK)
                    {
                        ShowBluetoothcControlPanel();
                    }
                }
                else if ((uint)ex.HResult == 0x80070005)
                {
                    MessageBox.Show(AppResources.Msg_MissingCaps);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            findDevicesProgressBar.IsIndeterminate = false;
        }
        private int mac0;
        private int mac1;
        private int mac2;
        private int mac3;
        private int mac4;
        private int mac5;
        string displayName;
        int macNumber(string text) {
            int ret = 0;
            try
            {
                ret = int.Parse(text, System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            catch (Exception e)
            {
                
            }    
            return ret;
        }

        bool validateDataInput()
        {
            logLine1.Text = "";
            logLine2.Text = "";   
            int deviceNameLength = nameInputbox.Text.Length;
            if (deviceNameLength!=0)
            {
                if ((deviceNameLength > 20))
                {
                    logLine1.Text = nextMessageNumber() + AppResources.deviceNameTooLong;
                    return false;
                }
                displayName = nameInputbox.Text;
            }else{
                if (myListPicker.SelectedItem == null)
                {
                    logLine1.Text = nextMessageNumber() + AppResources.selectBluetoothDevice;
                    return false;
                }
                displayName = ((BluetoothDeviceRecord)myListPicker.SelectedItem).Name;
            }
            //check MAC
            bool ret = true;
            mac0 = macNumber(macInputBox1.Text);
            if((mac0<0)||(mac0>255)){
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            mac1 = macNumber(macInputBox2.Text);
            if ((mac1 < 0) || (mac1 > 255))
            {
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            mac2 = macNumber(macInputBox3.Text);
            if ((mac2 < 0) || (mac2 > 255))
            {
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            mac3 = macNumber(macInputBox4.Text);
            if ((mac3 < 0) || (mac3 > 255))
            {
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            mac4 = macNumber(macInputBox5.Text);
            if ((mac4 < 0) || (mac4> 255))
            {
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            mac5 = macNumber(macInputBox6.Text);
            if ((mac5 < 0) || (mac5 > 255))
            {
                logLine1.Text = nextMessageNumber() + AppResources.macInvalida;
                return false;
            }
            
            return ret;
        }

        private void SetStatusOutput(string newStatus)
        {
            // Update the status output UI element in the UI thread
            // (some of the callbacks are in a different thread that wouldn't be allowed
            // to modify the UI thread)
            Dispatcher.BeginInvoke(() => { transmissionButton.Content = AppResources.startTransmission; });
        }

        private void StopPublishingMessage()
        {
            if (_publishingMessageId != 0 && _device != null)
            {
                // Stop publishing the message
                _device.StopPublishingMessage(_publishingMessageId);
                _publishingMessageId = 0;
                // Update enabled / disabled state of buttons in the User Interface
                // Update status text for UI - only if activated
            }
        }

        private void MessageWrittenHandler(ProximityDevice sender, long messageid)
        {
            // Stop publishing the message
            StopPublishingMessage();
            Dispatcher.BeginInvoke(() => {
                logLine1.Text = nextMessageNumber() + AppResources.etiquetaGrabada;
                transmissionButton.Content = AppResources.startTransmission;
                transmitting = false;
                transmissionProgressBar.IsIndeterminate = false;
            });
            
        }

        private void startTransmission(object sender, System.Windows.Input.GestureEventArgs e)
        {

            if(!validateDataInput()){
                return;
            }

            _device = ProximityDevice.GetDefault();
            // Update status text for UI
            if (!transmitting)
            {
                
                transmissionButton.Content = AppResources.stopTransmission;
                transmitting = true;

                int bodDataLength = 2 + 6 + 1 + 1 + displayName.Length + 1 + 1 + 3 + 1 + 1 + 6;
                byte[] bodData = new byte[bodDataLength];
                byte nfedHeaderLength = 1 + 1 + 1 + 32;
                byte[] nfedHeader = new byte[nfedHeaderLength];

                //Preparamos la cabecera del mensaje NFED
                nfedHeader[0] = 0xD2;
                nfedHeader[1] = 0x20;
                nfedHeader[2] = (byte)bodDataLength;
                string mimeType = "application/vnd.bluetooth.ep.oob";
                System.Buffer.BlockCopy(System.Text.Encoding.UTF8.GetBytes(mimeType), 0, nfedHeader, 3, mimeType.Length);
                //Ahora, pereparamos los datos BOD
                bodData[0] = (byte)bodDataLength;
                bodData[1] = 0x00;
                bodData[2] = (byte)mac5;//MAC
                bodData[3] = (byte)mac4;
                bodData[4] = (byte)mac3;
                bodData[5] = (byte)mac2;
                bodData[6] = (byte)mac1;
                bodData[7] = (byte)mac0;
                bodData[8] = (byte)(displayName.Length + 1);
                bodData[9] = 0x09;//Name length
                System.Buffer.BlockCopy(System.Text.Encoding.UTF8.GetBytes(displayName), 0, bodData, 10, displayName.Length);
                int nextIndex = displayName.Length+10;
                bodData[nextIndex + 0] = (byte)0x04;
                bodData[nextIndex + 1] = (byte)0x0D;
                bodData[nextIndex + 2] = (byte)0x18;
                bodData[nextIndex + 3] = (byte)0x04;
                bodData[nextIndex + 4] = (byte)0x20;

                bodData[nextIndex + 5] = (byte)0x07;
                bodData[nextIndex + 6] = (byte)0x03;
                bodData[nextIndex + 7] = (byte)0x08;
                bodData[nextIndex + 8] = (byte)0x11;
                bodData[nextIndex + 9] = (byte)0x0A;
                bodData[nextIndex + 10] = (byte)0x11;
                bodData[nextIndex + 11] = (byte)0x0C;
                bodData[nextIndex + 12] = (byte)0x11;

                var dataToWrite = new byte[nfedHeader.Length + bodData.Length];
                nfedHeader.CopyTo(dataToWrite, 0);
                bodData.CopyTo(dataToWrite, nfedHeader.Length);

                _publishingMessageId = _device.PublishBinaryMessage( "NDEF:WriteTag", dataToWrite.AsBuffer(), MessageWrittenHandler );
                logLine1.Text = nextMessageNumber() + AppResources.tapTagToBurn;
                logLine2.Text = "";
                transmissionProgressBar.IsIndeterminate = true;
            }else
            {
                StopPublishingMessage();
                transmissionButton.Content = AppResources.startTransmission;
                transmitting = false;
                transmissionProgressBar.IsIndeterminate = false;
            }
            
            
        }
        
    }
}